/**
 *  @file ObjPtrT.h
 */
#ifndef _OBJPTRT_H_
#define _OBJPTRT_H_

#include "CppMemPool.h"
#include "BaseObject.h"
#include "MemReleasePool.h"

namespace cppflib
{

/**
 *  A class to wrap around a raw pointer and is guaranteed to be released upon
 *  function exiting (or jumping out of a scope)
 */
template <typename TYPE>
class ObjPtrT : public NoCopyAndNew
{
private:
   TYPE *ptr;

private:
   ObjPtrT() { }

public:
   explicit ObjPtrT(TYPE * p) { this->ptr = p; cppmempool::UnlinkFromPool(this->ptr); }
   ~ObjPtrT() { cppmempool::Release(ptr); }
   operator TYPE*() const { return ptr; }
   operator const TYPE*() const { return ptr; }
   TYPE* operator->() const { return ptr; }
   TYPE *Ptr() { return ptr; }

};


/**
 *  A simple class just to keep a reference to a BaseObject derived instance
 */
template <typename TYPE>
class ReferenceT : public BaseObject
{
protected:
   TYPE *ptr;

protected:
   ReferenceT() { }

public:
   explicit ReferenceT(TYPE * p) 
   { 
      this->ptr = p;
      cppmempool::Retain(this->ptr);
   }

   virtual ~ReferenceT() { cppmempool::Release(ptr); }
   virtual TYPE *Ptr() { return ptr; }
};

/**
 *  A class to keep a weak reference to a BaseObject derived instance
 *
 *  WeakReference won't retain and release a pointer but will let it get collected 
 *  by auto release pool
 */
template <typename TYPE>
class WeakReferenceT : public ReferenceT<TYPE>
{
private:
   int refToken;

private:
   WeakReferenceT() { }

public:
   explicit WeakReferenceT(TYPE * p) 
   { 
      this->refToken = ::MRP_AssignWeakRefToken(p);
      this->ptr = p;
   }

   virtual ~WeakReferenceT() { this->ptr = NULL; } // so that base class won't release it

   bool IsAlive() { return (::MRP_IsWeakRefTokenEqual(this->ptr, refToken) == TRUE); }
   virtual TYPE *Ptr() { return IsAlive() ? this->ptr : NULL; }
};


}  // namespace cppflib

#endif
